<template>
  <div class="cases-view">
    <div class="cases-layout">
      <!-- 左侧项目导航 -->
      <div class="cases-sidebar">
        <div class="sidebar-header">
          <div class="sidebar-search">
            <input type="text" v-model="projectPagination.keyword" placeholder="搜索项目" class="search-input" />
            <el-icon class="search-icon">
              <Search />
            </el-icon>
          </div>
        </div>
        <div class="sidebar-list" ref="projectListRef" @scroll="onProjectListScroll">
                     <div v-for="project in projects.list" :key="project.itemList.ID" @click="selectProject(project)" :class="['sidebar-item', { 'is-selected': selectedProject === project.itemList.ID }]">
             <div class="sidebar-item-content">
               <div class="sidebar-item-header">
                 <div class="sidebar-item-title">{{ project.itemList.itemName }}</div>
                 <div class="sidebar-item-status" :style="{ backgroundColor: project.itemList.color }"></div>
               </div>
               <div class="sidebar-item-meta">
                 <div class="meta-item">
                   <el-icon class="meta-icon">
                     <Document />
                   </el-icon>
                   <span class="meta-label">总用例</span>
                   <span class="meta-value">{{ project.demandCaseTotal + project.projectCaseTotal }}</span>
                 </div>
                 <div class="meta-divider"></div>
                 <div class="meta-item">
                   <span class="meta-label">项目用例</span>
                   <span class="meta-value project-value">{{ project.projectCaseTotal }}</span>
                 </div>
                 <div class="meta-divider"></div>
                 <div class="meta-item">
                   <span class="meta-label">需求用例</span>
                   <span class="meta-value demand-value">{{ project.demandCaseTotal || 0 }}</span>
                 </div>
                                </div>
               </div>
           </div>
          <div v-if="projects.list.length === 0" class="sidebar-empty">
            未找到匹配的项目
          </div>
          <div class="sidebar-footer">
            <span v-if="isProjectLoading">加载中...</span>
            <span v-else-if="!hasMoreProjects && projects.list.length">没有更多了</span>
          </div>
        </div>
        
      </div>

      <!-- 主内容区 -->
      <div class="cases-main">
        <!-- 顶部筛选区 -->
        <div class="main-header">
          <div class="main-header-inner">
            <div class="tabs">
              <div v-for="tab in caseTabs" :key="tab.id" @click="selectActiveTab(tab.id)" :class="['tab', { 'is-active': activeTab === tab.id }]">
                <span>{{ tab.name }}</span>
              </div>
            </div>

            <div class="main-toolbar">
            </div>
          </div>
        </div>

        <!-- 用例列表区 -->
        <div class="main-content">
          <!-- 项目用例视图 -->
          <template v-if="activeTab === 'project'">
            <template v-if="selectedProject">
              <div class="section-gap project-cases-container">
                                 <div class="project-header" :style="{ backgroundColor: `${selectedProjectDetails?.itemList.color}10` }">
                   <div class="project-header-accent" :style="{ backgroundColor: selectedProjectDetails?.itemList.color }"></div>
                   <span class="project-header-title">{{ selectedProjectDetails?.itemList.itemName }}</span>
                 </div>
                
                <!-- 模块选择器 -->
                <div class="module-selector">
                  <div class="module-section">
                    <div class="module-title">一级功能模块</div>
                    <div class="module-tags">
                      <div v-if="!oneModules || oneModules.length === 0" class="module-empty">
                        暂无模块数据
                      </div>
                      <div v-else v-for="module in oneModules" :key="module.ID" 
                           :class="['module-tag', { 'is-selected': selectedPrimaryModules.includes(module.ID) }]">
                        <div class="module-tag-content" @click="togglePrimaryModule(module.ID)">
                          {{ module.itemItemModuleName }}
                          <span class="module-count" v-if="module.testCaseCount !== undefined">({{ module.testCaseCount }})</span>
                        </div>
                                                 <el-dropdown @command="(command: string) => handleModuleCommand(command, module)" trigger="click">
                           <el-button type="text" size="small" class="module-actions-btn">
                             <el-icon><MoreFilled /></el-icon>
                           </el-button>
                           <template #dropdown>
                             <el-dropdown-menu>
                               <el-dropdown-item command="edit">编辑</el-dropdown-item>
                               <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
                             </el-dropdown-menu>
                           </template>
                         </el-dropdown>
                      </div>
                      <el-button type="primary" size="small" @click="() => openModuleDialogAddVisible()" class="add-module-btn">
                        <el-icon><Plus /></el-icon>
                        添加模块
                      </el-button>
                    </div>
                  </div>
                  
                  <div class="module-section" v-if="selectedPrimaryModules.length > 0">
                    <div class="module-title">二级功能模块</div>
                    <div class="module-tags">
                      <div v-if="!twoModules || twoModules.length === 0" class="module-empty">
                        暂无二级模块
                      </div>
                      <div v-else v-for="module in twoModules" :key="module.ID" 
                           :class="['module-tag', { 'is-selected': selectedSubModules.includes(module.ID) }]">
                        <div class="module-tag-content" @click="toggleSubModule(module.ID)">
                          {{ module.itemItemModuleName }}
                          <span class="module-count" v-if="module.testCaseCount !== undefined">({{ module.testCaseCount }})</span>
                        </div>
                                                 <el-dropdown @command="(command: string) => handleModuleCommand(command, module)" trigger="click">
                           <el-button type="text" size="small" class="module-actions-btn">
                             <el-icon><MoreFilled /></el-icon>
                           </el-button>
                           <template #dropdown>
                             <el-dropdown-menu>
                               <el-dropdown-item command="edit">编辑</el-dropdown-item>
                               <el-dropdown-item command="link-cases">关联用例</el-dropdown-item>
                               <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
                             </el-dropdown-menu>
                           </template>
                         </el-dropdown>
                      </div>
                      <el-button type="primary" size="small" @click="() => openModuleDialogAddTwoVisible(selectedPrimaryModules[0])" class="add-module-btn" :disabled="selectedPrimaryModules.length !== 1">
                        <el-icon><Plus /></el-icon>
                        添加二级模块
                        <span v-if="selectedPrimaryModules.length !== 1" style="font-size: 11px; margin-left: 4px;">(请先选择一个一级模块)</span>
                      </el-button>
                    </div>
                  </div>
                </div>

                <el-table :data="projectCases" style="width: 100%" :border="true">
                  <el-table-column label="用例编号" prop="testCaseIndex" min-width="80" />
                  <el-table-column label="一级功能模块" prop="funcModules" width="150" />
                  <el-table-column label="二级功能模块" prop="funcModulesChild" width="150" />
                  <el-table-column label="用例名称" prop="testCaseName" min-width="200" />
                  <el-table-column label="前置条件" width="280">
                    <template #default="{ row }">
                      <pre style="margin: 0; font-family: inherit;">{{ row.beforeConditions }}</pre>
                    </template>
                  </el-table-column>
                  <el-table-column label="操作步骤" width="280">
                    <template #default="{ row }">
                      <pre style="margin: 0; font-family: inherit;">{{ row.operationSteps }}</pre>
                    </template>
                  </el-table-column>
                  <el-table-column label="预期结果" width="180">
                    <template #default="{ row }">
                      <pre style="margin: 0; font-family: inherit;">{{ row.expectedResult }}</pre>
                    </template>
                  </el-table-column>
                  <el-table-column label="操作" width="180" fixed="right">
                    <template #default="{ row }">
                      <div class="table-actions">
                        <el-button type="primary" size="small" plain @click.stop="showCaseDetail(row.ID)" class="btn-compact">
                          <el-icon>
                            <View />
                          </el-icon>
                        </el-button>
                        <el-button type="warning" size="small" plain @click.stop="editCase(row)" class="btn-compact">
                          <el-icon>
                            <Edit />
                          </el-icon>
                        </el-button>
                      </div>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </template>
          </template>

          <!-- 需求用例视图 -->
          <template v-else-if="activeTab === 'requirement'">
            <div class="section-gap">
              <div class="cards-grid requirements-grid" ref="reqGridRef" @scroll="onReqScroll">
                                 <div v-for="req in visibleRequirements" :key="req.id" @click="selectRequirement(req)" @dblclick="showRequirementCasesDialog(req)" :class="['card', { 'is-selected': selectedRequirement === req.ID }]">
                   <div class="card-title-row">
                     <span class="card-title">{{ req.RequirementName }}</span>
                                           <div class="card-tags">
                        <el-tag v-if="req.ContactTestNames && req.ContactTestNames.trim()" size="small" effect="plain" class="tester-tag">
                          {{ req.ContactTestNames }}
                        </el-tag>
                      </div>
                   </div>
                   <div class="card-sub"><span class="count-highlight">{{ req.TestCaseCount }}</span> 个关联用例</div>
                 </div>
                <div class="list-footer" v-if="!hasMoreReqCards && (filteredRequirements?.length || 0)">没有更多了</div>
              </div>
            </div>
          </template>

          <!-- 本月新增用例视图 -->
          <template v-else-if="activeTab === 'new'">
            <div class="section-gap">
              <div class="tester-summary">
                <div class="summary-left">本月合计：<span class="count-highlight">{{ newCaseTotal }}</span> 个</div>
                <div class="tester-tags">
                  <el-tag
                    size="large"
                    effect="plain"
                    :class="['tester-tag', { 'is-active': !selectedTester }]"
                    @click="selectTester('')"
                  >
                    全部：{{ newCaseTotal }}
                  </el-tag>
                  <el-tag
                    v-for="t in testers"
                    :key="t.UserName"
                    size="large"
                    effect="plain"
                    :class="['tester-tag', { 'is-active': selectedTester === t.UserName }]"
                    @click="selectTester(t.UserName)"
                  >
                    {{ t.UserName }}：{{ t.Count }}
                  </el-tag>
                </div>
              </div>
              <div class="cards-grid new-req-grid" ref="newReqGridRef" @scroll="onNewReqScroll">
                <div v-for="req in newRequirements" :key="req.RequirementName" @click="selectNewRequirement(req)" @dblclick="showNewCasesDialog(req)" :class="['card', { 'is-selected': selectedNewRequirement === req.RequirementName }]">
                  <div class="card-title-row">
                    <span class="card-title">{{ req.RequirementName }}</span>
                    <el-tag size="small" effect="plain" class="neutral-tag">{{ req.UserName }}</el-tag>
                  </div>
                  <div class="card-sub"><span class="count-highlight">{{ req.Count }}</span> 个新增用例</div>
                  <div class="card-sub audit-sub">
                    <span class="audit-badge audit-badge--pending">未审核 {{ req.AuditPendingCount ?? 0 }}</span>
                    <span class="audit-badge audit-badge--passed">已审核 {{ req.AuditPassedCount ?? 0 }}</span>
                  </div>
                </div>
                <div class="list-footer" v-if="isNewReqLoading">加载中...</div>
                <div class="list-footer" v-else-if="!hasMoreNewReq && (newRequirements?.length || 0)">没有更多了</div>
              </div>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>
  
  <!-- 添加一级模块对话框 -->
  <el-dialog v-model="moduleDialogAddVisible" title="添加一级模块" width="500px" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="itemItemModuleName" label-width="100px">
      <el-form-item label="模块名称">
        <el-input v-model="itemItemModuleName" placeholder="请输入模块名称" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeModuleDialogAddVisible">取消</el-button>
        <el-button type="primary" @click="submitModuleDialogAddVisible">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 审核对话框 -->
  <el-dialog v-model="reviewDialogVisible" title="审核新增用例" width="700px" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="reviewForm" label-width="100px">
      <el-form-item label="用例名称">
        <el-input v-model="reviewForm.testCaseName" readonly />
      </el-form-item>
      <el-form-item label="前置条件">
        <el-input v-model="reviewForm.beforeConditions" type="textarea" :rows="2" readonly />
      </el-form-item>
      <el-form-item label="测试步骤">
        <el-input v-model="reviewForm.operationSteps" type="textarea" :rows="4" readonly />
      </el-form-item>
      <el-form-item label="预期结果">
        <el-input v-model="reviewForm.expectedResult" type="textarea" :rows="3" readonly />
      </el-form-item>
      <el-form-item label="质量">
        <el-select v-model="reviewForm.quality" style="width: 220px" @change="calculateScore">
          <el-option label="优秀" value="excellent" />
          <el-option label="良好" value="good" />
          <el-option label="一般" value="average" />
          <el-option label="较差" value="poor" />
        </el-select>
      </el-form-item>
      <el-form-item label="评分">
        <el-input v-model.number="reviewForm.score" style="width: 120px" />
      </el-form-item>
      <el-form-item label="点评">
        <el-input v-model="reviewForm.comment" type="textarea" :rows="3" placeholder="请输入审核意见" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="reviewDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitReview">提交审核</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑一级模块对话框 -->
  <el-dialog v-model="moduleDialogEditVisible" title="编辑一级模块" width="500px" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="itemItemModuleName" label-width="100px">
      <el-form-item label="模块名称">
        <el-input v-model="itemItemModuleName" placeholder="请输入模块名称" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeModuleDialogEditVisible">取消</el-button>
        <el-button type="primary" @click="submitModuleDialogEditVisible">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 添加二级模块对话框 -->
  <el-dialog v-model="moduleDialogAddTwoVisible" title="添加二级模块" width="500px" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="itemItemModuleName" label-width="100px">
      <el-form-item label="模块名称">
        <el-input v-model="itemItemModuleName" placeholder="请输入模块名称" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeModuleDialogAddTwoVisible">取消</el-button>
        <el-button type="primary" @click="submitModuleDialogAddTwoVisible">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑二级模块对话框 -->
  <el-dialog v-model="moduleDialogEditTwoVisible" title="编辑二级模块" width="500px" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="itemItemModuleName" label-width="100px">
      <el-form-item label="模块名称">
        <el-input v-model="itemItemModuleName" placeholder="请输入模块名称" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeModuleDialogEditVisible">取消</el-button>
        <el-button type="primary" @click="submitModuleDialogEditTwoVisible">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 关联用例对话框 -->
  <el-dialog v-model="linkCasesDialogVisible" title="关联用例" width="1200px" :modal-append-to-body="false" :append-to-body="false">
    <div class="link-cases-container">
      <div class="link-cases-header">
        <h4>为模块【{{ itemItemModuleName }}】关联用例</h4>
      </div>
      
      <div class="link-cases-content">
        <!-- 左侧：可选择的用例列表 -->
        <div class="left-panel">
                                <div class="panel-header">
             <h5>可选择的用例</h5>
             <div class="search-controls">
               <span class="form-label">需求筛选：</span>
                               <el-select 
                  v-model="searchRequirementQuery" 
                  placeholder="全部需求"
                  clearable
                  filterable
                  size="small"
                  @change="handleRequirementTolinkChange"
                  style="width: 180px;"
                >
                 <el-option label="全部需求" :value="0" />
                 <el-option 
                   v-for="req in allRequirementToLink" 
                   :key="req.id" 
                   :label="req.requirementName" 
                   :value="req.id" 
                 />
               </el-select>

             </div>
           </div>
          
          <el-table 
            :data="allCasesToLink" 
            :height="'calc(100% - 110px)'"
            size="small"
            stripe
            @selection-change="handleLeftSelectionChange"
            ref="leftTable"
          >
            <el-table-column type="selection" width="55" />
            <el-table-column label="用例名称" prop="testCaseName" />
            <el-table-column label="一级模块" prop="funcModules" width="140" />
            <el-table-column label="二级模块" prop="funcModulesChild" width="160" />
          </el-table>
          
          <div class="panel-actions">
            <el-button type="primary" size="small" @click="addSelectedCases">
              添加到已关联 →
            </el-button>
          </div>
        </div>
        
        <!-- 右侧：已关联的用例列表 -->
        <div class="right-panel">
          <div class="panel-header">
            <h5>已关联的用例</h5>
          </div>
          
          <el-table :data="linkedCases" :height="'calc(100% - 60px)'" size="small" stripe>
            <el-table-column label="用例名称" prop="testCaseName" show-overflow-tooltip />
            <el-table-column label="一级模块" prop="funcModules" width="140" show-overflow-tooltip />
            <el-table-column label="二级模块" prop="funcModulesChild" width="160" show-overflow-tooltip />
            <el-table-column label="操作" width="100">
              <template #default="{ row }">
                <el-button 
                  type="danger" 
                  size="small" 
                  @click="unlinkLinkeModulCase(row)"
                >
                  取消关联
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </div>
    
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeLinkCasesDialogVisible">取消</el-button>
        <el-button type="primary" @click="confirmLinkCases">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 查看用例对话框 -->
  <el-dialog v-model="caseDetailVisible" title="用例详情" width="800px" :close-on-click-modal="false" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="caseDetail" label-width="100px">
      <el-form-item label="用例名称">
        <el-input v-model="caseDetail.testCaseName" readonly />
      </el-form-item>
      <el-form-item label="前置条件">
        <el-input v-model="caseDetail.beforeConditions" type="textarea" :rows="3" readonly />
      </el-form-item>
      <el-form-item label="测试步骤">
        <el-input v-model="caseDetail.operationSteps" type="textarea" :rows="6" readonly />
      </el-form-item>
      <el-form-item label="预期结果">
        <el-input v-model="caseDetail.expectedResult" type="textarea" :rows="4" readonly />
      </el-form-item>
      <el-form-item label="实际结果">
        <el-input v-model="caseDetail.realResult" type="textarea" :rows="4" readonly />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="caseDetailVisible = false">关闭</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑用例对话框 -->
  <el-dialog v-model="caseEditVisible" title="编辑用例" width="800px" :close-on-click-modal="false" :modal-append-to-body="false" :append-to-body="false">
    <el-form :model="caseDetail" label-width="100px">
      <el-form-item label="用例名称">
        <el-input v-model="caseDetail.testCaseName" placeholder="请输入用例名称" />
      </el-form-item>
      <el-form-item label="前置条件">
        <el-input v-model="caseDetail.beforeConditions" type="textarea" :rows="3" placeholder="请输入前置条件" />
      </el-form-item>
      <el-form-item label="测试步骤">
        <el-input v-model="caseDetail.operationSteps" type="textarea" :rows="6" placeholder="请输入测试步骤" />
      </el-form-item>
      <el-form-item label="预期结果">
        <el-input v-model="caseDetail.expectedResult" type="textarea" :rows="4" placeholder="请输入预期结果" />
      </el-form-item>
      <el-form-item label="实际结果">
        <el-input v-model="caseDetail.realResult" type="textarea" :rows="4" placeholder="请输入实际结果" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="caseEditVisible = false">取消</el-button>
        <el-button type="primary" @click="updateItemCaseById">保存</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 需求用例对话框 -->
  <el-dialog v-model="requirementCasesDialogVisible" :title="`需求用例 - ${selectedRequirementName}`" width="900px" :close-on-click-modal="false" :modal-append-to-body="false" :append-to-body="false">
    <el-table :data="requirementCasesList" height="420" size="small" stripe @scroll="onReqCasesScroll" ref="reqCasesScrollRef">
      <el-table-column label="用例名称" prop="testCaseName" show-overflow-tooltip />
      <el-table-column label="一级模块" prop="funcModules" width="160" show-overflow-tooltip />
      <el-table-column label="二级模块" prop="funcModulesChild" width="180" show-overflow-tooltip />
      <el-table-column label="操作" width="140" fixed="right">
        <template #default="{ row }">
          <el-button size="small" type="primary" plain @click.stop="showCaseDetail(row.ID)">查看</el-button>
          <el-button size="small" type="warning" plain @click.stop="editCase(row)">编辑</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="list-footer" v-if="isReqCasesLoading">加载中...</div>
    <div class="list-footer" v-else-if="!hasMoreReqCases && (requirementCasesList?.length || 0)">没有更多了</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="requirementCasesDialogVisible = false">关闭</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 本月新增用例对话框 -->
  <el-dialog v-model="newCasesDialogVisible" :title="`本月新增用例 - ${selectedNewRequirement}`" width="900px" :close-on-click-modal="false" :modal-append-to-body="false" :append-to-body="false">
    <el-table :data="newCasesList" height="420" size="small" stripe @scroll="onNewCasesScroll" ref="newCasesScrollRef">
      <el-table-column label="用例名称" prop="testCaseName" show-overflow-tooltip />
      <el-table-column label="一级模块" prop="funcModules" width="160" show-overflow-tooltip />
      <el-table-column label="二级模块" prop="funcModulesChild" width="180" show-overflow-tooltip />
      <el-table-column label="操作" width="280" fixed="right">
        <template #default="{ row }">
          <div class="op-gap">
            <el-button size="small" type="primary" plain @click.stop="showCaseDetail(row.ID)">查看</el-button>
            <el-button size="small" type="warning" plain @click.stop="editCase(row)">编辑</el-button>
            <el-button v-if="row.isAudit !== 1" size="small" type="success" plain @click.stop="showReviewDialog(row)">审核</el-button>
            <el-button v-else size="small" type="primary" @click.stop="showReviewDialog(row)" class="reviewed-btn">已审核</el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <div class="list-footer" v-if="isNewCasesLoading">加载中...</div>
    <div class="list-footer" v-else-if="!hasMoreNewCases && (newCasesList?.length || 0)">没有更多了</div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="newCasesDialogVisible = false">关闭</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, computed, reactive, watch, onMounted } from 'vue';
import { Search, Document, Plus, MoreFilled, View, Edit, Clock } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import {
  GetAllItemCaseNumber,
  GetItemCaseListById,
  AddItemModuleOne,// 添加项目一级功能分类
  AddItemModuleTwo,// 添加项目二级功能分类
  GetDeleteItemCaseModuleOneById,// 删除一级功能模块
  GetDeleteItemCaseModuleTwoById,// 删除二级功能模块
  GetItemTwoModuleList,//获取选中一级功能分类的所有二级分类
  UpdateItemModuleOne,//编辑项目一级功能分类
  UpdateItemModuletwo,//编辑项目二级功能分类
  GetItemOneModuleList,//获取项目所有一级功能模块
  GetItemModuleCaseList,//获取项目模块对应的用例
  GetItemRequirementCaseList,// 查询选中项目的所有需求用例
  GetItemRequirementList,// 查询选中项目的所有需求
  AddOneTwoModulItemRequirementList,// 一级模块和二级模块关联用例
  GetLinkeModulList,// 查询模块已经关联的用例
  UnlinkLinkeModulCase,// 取消模块已经关联的用例
  GetItemCaseById,// 查询用例详情
  DeleteItemCaseById,// 删除指定用例
  UpdateItemCaseById,// 更新用例详情
  GetItemRequirementListById,// 获取项目下的所有需求
  GetFatherTestCaseListPage,// 获取需求所有测试用例
  GetNowMonthAddCaseTotal,// 获取本月测试新增用例数
  GetNowMonthAddCaseRequirement,// 获取本月测试新增用例的需求
  GetNowMonthAddCaseByRequirementName,// 根据选中需求的名称获取新增用例
  AuditNowMonthAddCaseById,// 审核本月新增用例
} from "@/api/newDemands/index";

// 搜索和筛选状态
const activeTab = ref('project');
const selectedProject = ref(3);//选中的当前需求
const selectedTester = ref<string | null>(null);
const selectedNewRequirement = ref<string>('');
const selectedRequirement = ref<number>(0);
const selectedPrimaryModules = ref<number[]>([]);//选中的一级模块
const selectedSubModules = ref<number[]>([]);//二级模块
const moduleDialogAddVisible = ref(false)//添加模块模态框
const moduleDialogAddTwoVisible = ref(false)//添加二级模块模态框
const moduleDialogEditVisible = ref(false)//编辑模块模态框
const moduleDialogEditTwoVisible = ref(false)//编辑二级模块模态框
// 新增用例模态框状态
const newCasesDialogVisible = ref(false);
const selectedRequirementName = ref('');
// 新增状态变量
const requirementCasesDialogVisible = ref(false);
const leftSelectedCases = ref<any[]>([]); // 左侧选中的用例
const leftTable = ref(); // 左侧表格引用
// 左侧表格选中变化
const handleLeftSelectionChange = (selection: any[]) => {
  leftSelectedCases.value = selection;
};

// 添加选中的用例到已关联列表
const addSelectedCases = () => {
  // 过滤掉已经存在的用例
  const newCases = leftSelectedCases.value.filter((caseItem: any) =>
    !linkedCases.value.some((linkedCase: any) => linkedCase.ID === caseItem.ID)
  );

  // 添加到右侧
  linkedCases.value = [...linkedCases.value, ...newCases];

  // 从左侧移除已添加的用例
  allCasesToLink.value = allCasesToLink.value.filter(
    caseItem => !leftSelectedCases.value.some(selected => selected.ID === caseItem.ID)
  );

  // 清空左侧选中状态
  leftTable.value.clearSelection();
  leftSelectedCases.value = [];
};

// 保留原有的取消关联方法
const unlinkLinkeModulCase = async (row: any) => {
  // 找到要移除的用例（统一使用后端返回的大写 ID 字段）
  const caseToRemove = linkedCases.value.find((caseItem: any) => caseItem.ID === row.ID);

  if (caseToRemove) {
    // 从右侧移除
    linkedCases.value = linkedCases.value.filter((caseItem: any) => caseItem.ID !== row.ID);

    // 添加回左侧
    allCasesToLink.value = [...allCasesToLink.value, caseToRemove];

    // 按需调用API取消关联
    const { data } = await UnlinkLinkeModulCase(row.ID);
    if (data.code == 200) {
      ElMessage.success(data.msg);
      // 刷新相关数据
      getItemTwoModuleList();
      getItemModuleCaseList();
    } else {
      ElMessage.error(data.msg);
    }
  }
};
// 显示新增用例模态框
const showNewCasesDialog = (req: any) => {
  selectedRequirementName.value = req.RequirementName;
  selectedNewRequirement.value = req.RequirementName;
  requirementCasePagination.value.requirementName = req.RequirementName;
  requirementCasePagination.value.userName = req.UserName;
  newCasesDialogVisible.value = true;
  getNowMonthAddCaseByRequirementName();
};

// 分页相关变量
const projectPagination = ref({
  page: 1,
  pageSize: 15, // 首次展示15条
  keyword: ''
})

// 项目列表懒加载配置
const projectInitPageSize = 15 // 首次加载15条
const projectStepPageSize = 5  // 后续每次加载5条

// 左侧项目列表懒加载相关
const projectListRef = ref<HTMLElement | null>(null)
const isProjectLoading = ref(false)
const hasMoreProjects = ref(true)
let projectSearchDebounceTimer: any = null

// 监听左侧项目搜索关键词，输入后自动生效（防抖）
watch(
  () => projectPagination.value.keyword,
  () => {
    if (projectSearchDebounceTimer) clearTimeout(projectSearchDebounceTimer)
    projectSearchDebounceTimer = setTimeout(() => {
      // 重置分页状态
      projectPagination.value.page = 1
      hasMoreProjects.value = true
      // 重置列表以便更快感知到变化
      projects.value.list = [] as any
      projects.value.total = 0
      getAllItemCaseNumber(false) // 首次加载，不使用追加模式
    }, 300)
  }
)

// 左侧项目列表滚动触底加载
const onProjectListScroll = (e: Event) => {
  const el = e.target as HTMLElement
  if (!el || isProjectLoading.value || !hasMoreProjects.value) return
  const threshold = 40
  const reachedBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - threshold
  if (reachedBottom) {
    projectPagination.value.page += 1
    getAllItemCaseNumber(true) // 传递isAppend参数，表示追加加载
  }
}

const selectUser = ref("");
// 选中菜单按钮
const selectActiveTab = (activeTabValue: any) => {
  activeTab.value = activeTabValue;
  // 获取当前项目的所有需求
  if (activeTabValue === 'requirement') {
    getItemRequirementListById();
  }
  if (activeTabValue === 'new') {
    getNowMonthAddCaseTotal();
  }

}

// 测试人员数据
const testers = ref();
// 获取本月测试新增用例数
const getNowMonthAddCaseTotal = async () => {
  const { data } = await GetNowMonthAddCaseTotal();
  if (data.code == 200) {
    newCaseTotal.value = data.data.reduce((sum: number, item: any) => sum + item.Count, 0);
    testers.value = data.data;
    getNowMonthAddCaseRequirement();
  } else {
    ElMessage.error(data.msg)
  }
}


// 模块编辑对话框
const moduleDialog = ref({
  visible: false,
  title: '添加模块',
  mode: 'add', // 'add' | 'edit' | 'add-sub'
  currentModule: null as any
});

const moduleForm = ref({
  id: '',
  name: '',
  parentId: ''
});


// 用例编辑对话框
const caseEdit = reactive({
  visible: false,
  title: '编辑用例',
  form: {
    id: '',
    name: '',
    module: '',
    subModule: '',
    tester: '',
    precondition: '',
    steps: [] as Array<{ action: string; expected: string }>,
    type: ''
  }
});

// 关联用例对话框
const linkCasesDialog = reactive({
  visible: false,
  moduleId: '',
  moduleName: '',
  caseType: 'requirement'
});
const newCaseTotal = ref(0)
// 用例类型标签
const caseTabs = [
  { id: 'project', name: '项目用例', count: 856 },
  { id: 'requirement', name: '需求用例', count: 342 },
  { id: 'new', name: '本月新增(项目过滤无效)', count: 50 }
];

const oneModules = ref();//模块列表

// 
const getItemOneModuleList = async () => {
  const { data } = await GetItemOneModuleList(selectedProject.value)
  if (data.code == 200) {
    // 为每个模块添加用例数量
    const modulesWithCount = await Promise.all(
      data.data.map(async (module: any) => {
        try {
          // 获取该模块的用例数量
          const caseParams = {
            "itemId": selectedProject.value,
            "itemItemModuleOneIds": [module.ID]
          };
          const caseResult = await GetItemModuleCaseList(caseParams);
          if (caseResult.data.code === 200) {
            module.testCaseCount = caseResult.data.data?.length || 0;
          } else {
            module.testCaseCount = 0;
          }
        } catch (error) {
          module.testCaseCount = 0;
        }
        return module;
      })
    );
    oneModules.value = modulesWithCount;
  } else {
    ElMessage.error(data.msg)
  }
}

// 项目数据
const projects = ref({
  list: [
    {
      demandCaseTotal: 0,
      projectCaseTotal: 0,
      itemList: {
        itemName: "",
        color: "",
        userId: 0,
        requirements: null,
        itemTests: null,
        itemFunctions: null,
        itemCase: null,
        itemTestCaseLibrarys: null,
        itemWikis: null,
        itemItemModule: null,
        ItemManagerId: 0,
        ID: 0,
        createAt: "",
        UpdatedAt: ""
      },
    }
  ],  // 默认空数组
  total: 0,
  page: 1,
  pageSize: 10
});

const selectedProjectDetails = computed(() => {
  return projects.value.list.find((project: any) => project.itemList.ID === selectedProject.value) || null;
});



//  所有需求
const filteredRequirements = ref<any[]>([]);
// 需求卡片懒加载（本页侧）
const visibleRequirements = ref<any[]>([])
const reqGridRef = ref<HTMLElement | null>(null)
const reqInitCount = 15
const reqStep = 8
const hasMoreReqCards = ref(true)
// 获取指定项目下的所有需求
const getItemRequirementListById = async () => {
  const { data } = await GetItemRequirementListById(selectedProject.value)
  if (data.code == 200) {
    filteredRequirements.value = data.data || [];
    // 初始化可见卡片
    visibleRequirements.value = filteredRequirements.value.slice(0, reqInitCount)
    hasMoreReqCards.value = filteredRequirements.value.length > visibleRequirements.value.length
  } else {
    ElMessage.error(data.msg)
  }
}
const onReqScroll = (e: Event) => {
  const el = e.target as HTMLElement
  if (!el || !hasMoreReqCards.value) return
  const threshold = 40
  const reachedBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - threshold
  if (reachedBottom) {
    const nextLen = visibleRequirements.value.length + reqStep
    visibleRequirements.value = filteredRequirements.value.slice(0, nextLen)
    hasMoreReqCards.value = filteredRequirements.value.length > visibleRequirements.value.length
  }
}


// 审核用例
const reviewDialogVisible = ref(false);
const reviewForm = ref({
  caseId: 0,
  testCaseName: '',
  beforeConditions: '',
  operationSteps: '',
  expectedResult: '',
  quality: 'excellent',
  score: 0,
  comment: ''
});

// Quality to score mapping
const qualityScoreMap: Record<'excellent' | 'good' | 'average' | 'poor', number> = {
  excellent: 100,
  good: 85,
  average: 60,
  poor: 40
};

const showReviewDialog = (row: any) => {

  reviewForm.value = {
    caseId: row.ID,
    testCaseName: row.testCaseName,
    beforeConditions: row.beforeConditions,
    operationSteps: row.operationSteps,
    expectedResult: row.expectedResult,
    quality: 'excellent',
    score: 100,
    comment: ''
  };
  reviewDialogVisible.value = true;
};

const calculateScore = () => {
  reviewForm.value.score = qualityScoreMap[reviewForm.value.quality as 'excellent' | 'good' | 'average' | 'poor'] || 0;
};

const submitReview = () => {

  if (reviewForm.value.quality == 'excellent') {
    reviewForm.value.quality = '优秀';
  }
  if (reviewForm.value.quality == 'good') {
    reviewForm.value.quality = '良好';
  }
  if (reviewForm.value.quality == 'average') {
    reviewForm.value.quality = '一般';
  }
  if (reviewForm.value.quality == 'poor') {
    reviewForm.value.quality = '较差';
  }

  reviewDialogVisible.value = false;
  auditNowMonthAddCaseById();
};

const auditNowMonthAddCaseById = async () => {
  const { data } = await AuditNowMonthAddCaseById(reviewForm.value)
  if (data.code == 200) {
    ElMessage.success(data.msg)
    // 刷新"本月新增用例"列表与顶部汇总
    getNowMonthAddCaseRequirement();
    getNowMonthAddCaseTotal();
  } else {
    ElMessage.error(data.msg)
  }
}

// 方法
const selectProject = (project: any) => {
  selectedProject.value = project.itemList.ID;
  selectedNewRequirement.value = '';
  selectedRequirement.value = 0;
  selectedPrimaryModules.value = [];
  selectedSubModules.value = [];
  // 查询选中需求的用例
  getItemCaseListById();
  // 查询选中用例的功能模块
  getItemOneModuleList();
  //获取项目模块对应的用例
  getItemModuleCaseList();
  // 查询项目需求
  getItemRequirementListById();
};



const selectTester = (testerId: string) => {
  selectedTester.value = testerId === selectedTester.value ? "" : testerId;
  selectUser.value = selectedTester.value
  // 重置懒加载状态并重新拉取
  newReqPage.value = 1
  hasMoreNewReq.value = true
  newRequirements.value = []
  getNowMonthAddCaseRequirement(false)
};

// 新增用例的需求
const newRequirements = ref<any[]>([]);
const newReqGridRef = ref<HTMLElement | null>(null)
const isNewReqLoading = ref(false)
const hasMoreNewReq = ref(true)
// 懒加载状态：初始 15，后续每次 +8
const newReqPage = ref(1)
const newReqPageSize = ref(15)
const newReqInit = 15
const newReqStep = 8

// 获取本月新增用例的需求
const getNowMonthAddCaseRequirement = async (isAppend = false) => {
  if (isNewReqLoading.value) return
  isNewReqLoading.value = true
  
  // 计算本次请求的页面大小
  let currentPageSize = newReqPageSize.value
  if (isAppend && newReqPage.value > 1) {
    // 第一次加载后，每次追加8条
    currentPageSize = newReqStep
  }
  
  const { data } = await GetNowMonthAddCaseRequirement({
    "userName": selectUser.value,
    "page": newReqPage.value,
    "pageSize": currentPageSize
  })
  if (data.code == 200) {
    const incoming: any[] = data.data?.list || data.data || [];
    const total = data.data?.total ?? undefined
    
    if (isAppend) {
      newRequirements.value = [...newRequirements.value, ...incoming]
    } else {
      // 初始加载：只显示前15条
      newRequirements.value = incoming.slice(0, newReqInit)
      hasMoreNewReq.value = incoming.length > newReqInit
    }
    
    if (typeof total === 'number') {
      hasMoreNewReq.value = newRequirements.value.length < total
    } else if (!isAppend) {
      hasMoreNewReq.value = incoming.length > newReqInit
    }
  } else {
    ElMessage.error(data.msg)
  }
  isNewReqLoading.value = false
}

const onNewReqScroll = (e: Event) => {
  const el = e.target as HTMLElement
  if (!el || isNewReqLoading.value || !hasMoreNewReq.value) return
  const threshold = 40
  const reachedBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - threshold
  if (reachedBottom) {
    // 增量加载：每次 +8 条
    newReqPage.value += 1
    getNowMonthAddCaseRequirement(true)
  }
}

const requirementCasePagination = ref({
  requirementName: "",
  userName: "",
  page: 1,
  pageSize: 15,
  keyword: ''
})

// 选中新增用例需求时触发的操作
const selectNewRequirement = (req: any) => {
  selectedNewRequirement.value = req.RequirementName === selectedNewRequirement.value ? "" : req.RequirementName;
  requirementCasePagination.value.requirementName = selectedNewRequirement.value;
  requirementCasePagination.value.requirementName = req.UserName;
};

const filteredNewCases = ref({
  list: [],
  total: 0,
  page: 1,
  pageSize: 6
});

// 本月新增用例弹窗懒加载状态（服务端分页：首屏15，后续每次10）
const newCasesList = ref<any[]>([])
const isNewCasesLoading = ref(false)
const hasMoreNewCases = ref(true)
const newCasesInitPageSize = 15
const newCasesStepPageSize = 10
const newCasesScrollRef = ref()

// 更新获取本月新增用例的方法（支持追加）
const getNowMonthAddCaseByRequirementName = async (isAppend = false) => {
  // 首次与翻页切换 pageSize
  if (!isAppend) {
    requirementCasePagination.value.page = 1
    requirementCasePagination.value.pageSize = newCasesInitPageSize
  }
  const { data } = await GetNowMonthAddCaseByRequirementName(requirementCasePagination.value)
  if (data.code == 200) {
    filteredNewCases.value = data.data
    const incoming: any[] = filteredNewCases.value.list || []
    if (isAppend) {
      newCasesList.value = [...newCasesList.value, ...incoming]
    } else {
      newCasesList.value = incoming
    }
    const total = filteredNewCases.value.total ?? incoming.length
    hasMoreNewCases.value = newCasesList.value.length < total
  } else {
    ElMessage.error(data.msg)
  }
}

// 本月新增用例弹窗滚动加载
const onNewCasesScroll = () => {
  if (isNewCasesLoading.value || !hasMoreNewCases.value) return
  const body = newCasesScrollRef.value?.$el?.querySelector('.el-scrollbar__wrap') || newCasesScrollRef.value?.$el
  if (!body) return
  const threshold = 80
  const reachedBottom = body.scrollTop + body.clientHeight >= body.scrollHeight - threshold
  if (reachedBottom) {
    isNewCasesLoading.value = true
    requirementCasePagination.value.page += 1
    requirementCasePagination.value.pageSize = newCasesStepPageSize
    getNowMonthAddCaseByRequirementName(true).finally(() => {
      isNewCasesLoading.value = false
      const wrap = newCasesScrollRef.value?.$el?.querySelector('.el-scrollbar__wrap') || newCasesScrollRef.value?.$el
      if (wrap) {
        wrap.scrollTop = Math.max(0, wrap.scrollTop - 40)
      }
    })
  }
}

// 选中需求时触发的操作
const selectRequirement = (req: any) => {
  // selectedRequirement.value = reqId === selectedRequirement.value ? 0 : reqId;
  selectedRequirement.value = req.ID;
};
// 新增显示需求用例模态框方法
const showRequirementCasesDialog = (req: any) => {
  selectedRequirementName.value = req.RequirementName;
  selectedRequirement.value = req.ID;
  casePagination.value.id = req.ID;
  requirementCasesDialogVisible.value = true;
  getFatherTestCaseList();
};


// 需求用例分页相关变量（用于服务端分页懒加载）
const casePagination = ref({
  id: 0,
  page: 1,
  pageSize: 15,
  keyword: ''
})

// 查询的所有用例
interface PaginatedList {
  list: [];
  total: number;
  page: number;
  pageSize: number;
}


const filteredRequirementCases = ref<PaginatedList>({
  list: [],
  total: 0,
  page: 1,
  pageSize: 10,
});
// 需求用例对话框懒加载状态
const requirementCasesList = ref<any[]>([])
const isReqCasesLoading = ref(false)
const hasMoreReqCases = ref(true)
const reqCasesScrollRef = ref()
// 首次显示条数与后续每次追加数量
const reqCasesInitPageSize = 15
const reqCasesStepPageSize = 10

// 首次或翻页获取
const getFatherTestCaseList = async (isAppend = false) => {
  casePagination.value.id = selectedRequirement.value;
  // 首次加载使用初始页大小，后续滚动采用 step 大小
  if (!isAppend) {
    casePagination.value.page = 1
    casePagination.value.pageSize = reqCasesInitPageSize
  }
  const { data } = await GetFatherTestCaseListPage(casePagination.value);
  if (data.code == 200) {
    filteredRequirementCases.value = data.data;
    const incoming = filteredRequirementCases.value.list || []
    if (isAppend) {
      requirementCasesList.value = [...requirementCasesList.value, ...incoming]
    } else {
      requirementCasesList.value = incoming
    }
    hasMoreReqCases.value = requirementCasesList.value.length < (filteredRequirementCases.value.total || 0)
  } else {
    ElMessage.error(data.msg)
  }
}

const onReqCasesScroll = () => {
  if (isReqCasesLoading.value || !hasMoreReqCases.value) return
  const body = reqCasesScrollRef.value?.$el?.querySelector('.el-scrollbar__wrap') || reqCasesScrollRef.value?.$el
  if (!body) return
  const threshold = 80
  const reachedBottom = body.scrollTop + body.clientHeight >= body.scrollHeight - threshold
  if (reachedBottom) {
    isReqCasesLoading.value = true
    casePagination.value.page += 1
    casePagination.value.pageSize = reqCasesStepPageSize
    getFatherTestCaseList(true).finally(() => {
      isReqCasesLoading.value = false
      // 轻微上滚，避免持续触发
      const wrap = reqCasesScrollRef.value?.$el?.querySelector('.el-scrollbar__wrap') || reqCasesScrollRef.value?.$el
      if (wrap) {
        wrap.scrollTop = Math.max(0, wrap.scrollTop - 40)
      }
    })
  }
}

//项目测试用例列表
const projectCases = ref([])
// 获取项目模块对应的用例
const getItemModuleCaseList = async () => {
  // 如果没有选择任何模块，显示所有用例
  const params: any = {
    "itemId": selectedProject.value
  };
  
  if (selectedPrimaryModules.value.length > 0) {
    params.itemItemModuleOneIds = selectedPrimaryModules.value;
  }
  
  if (selectedSubModules.value.length > 0) {
    params.itemItemModuleTwoIds = selectedSubModules.value;
  }

  try {
    const { data } = await GetItemModuleCaseList(params);

    if (data.code == 200) {
      projectCases.value = data.data;
    } else {
      ElMessage.error(data.msg);
    }
  } catch (error) {
    ElMessage.error('获取用例数据失败');
  }
}

//所有二级功能分类
const twoModules = ref();
// 获取选中的一级模块的所有二级模块
const getItemTwoModuleList = async () => {
  const { data } = await GetItemTwoModuleList({
    "itemItemModuleOneIds": selectedPrimaryModules.value
  })

  if (data.code == 200) {
    // 为每个二级模块添加用例数量
    const modulesWithCount = await Promise.all(
      data.data.map(async (module: any) => {
        try {
          // 获取该二级模块的用例数量
          const caseParams = {
            "itemId": selectedProject.value,
            "itemItemModuleTwoIds": [module.ID]
          };
          const caseResult = await GetItemModuleCaseList(caseParams);
          if (caseResult.data.code === 200) {
            module.testCaseCount = caseResult.data.data?.length || 0;
          } else {
            module.testCaseCount = 0;
          }
        } catch (error) {
          module.testCaseCount = 0;
        }
        return module;
      })
    );
    twoModules.value = modulesWithCount;
  } else {
    ElMessage.error(data.msg)
  }
}


// 选择模块
const togglePrimaryModule = (moduleId: number) => {
  const index = selectedPrimaryModules.value.indexOf(moduleId);
  if (index === -1) {
    selectedPrimaryModules.value.push(moduleId);
  } else {
    selectedPrimaryModules.value.splice(index, 1);
  }
  
  // 清除子模块选择
  selectedSubModules.value = [];
  
  // 获取项目模块对应的用例
  getItemModuleCaseList();
  
  // 获取选中的一级模块的所有二级模块
  getItemTwoModuleList();
};

const toggleSubModule = (moduleId: number) => {
  const index = selectedSubModules.value.indexOf(moduleId);
  if (index === -1) {
    selectedSubModules.value.push(moduleId);
  } else {
    selectedSubModules.value.splice(index, 1);
  }

  // 获取项目模块对应的用例
  getItemModuleCaseList();
};


// 用例详情对话框
const caseDetail = ref();
// 用例详情模态框
const caseDetailVisible = ref(false);
// 查询用例详情
const showCaseDetail = (id: any) => {
  getItemCaseById(id);//查询用例详情
};
// 查询用例详情
const getItemCaseById = async (id: any) => {
  const { data } = await GetItemCaseById(id)
  if (data.code == 200) {
    caseDetail.value = data.data;
    caseDetailVisible.value = true;
  } else {
    ElMessage.error(data.msg)
  }
}


// 编辑用例模态框
const caseEditVisible = ref(false)

// 编辑用例
const editCase = (ec: any) => {
  caseDetail.value = ec
  caseEditVisible.value = true;
};

// 删除指定用例
const deleteCase = (caseItem: any) => {
  ElMessageBox.confirm(`确定要删除用例 【${caseItem.testCaseName}】 吗？`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    deleteItemCaseById(caseItem.ID)
  }).catch(() => {
    // 用户取消
  });
};



// 删除指定用例
const deleteItemCaseById = async (id: any) => {
  const { data } = await DeleteItemCaseById(id)
  if (data.code == 200) {
    ElMessage.success(data.msg)
    getItemRequirementCaseList();
    getItemRequirementList();
    getItemModuleCaseList();
    getItemTwoModuleList();
    getItemCaseListById();
    getItemOneModuleList();
  } else {
    ElMessage.error(data.msg)
  }
}

// 修改用例
const saveCase = () => {
  // 验证必填项
  if (!caseDetail.value.testCaseName.trim()) {
    ElMessage.error('请输入用例名称');
    return;
  }
  if (!caseDetail.value.beforeConditions.trim()) {
    ElMessage.error('请输入用例前置条件');
    return;
  }
  if (!caseDetail.value.operationSteps.trim()) {
    ElMessage.error('请输入用例执行步骤');
    return;
  }
  if (!caseDetail.value.expectedResult.trim()) {
    ElMessage.error('请输入用例预期结果');
    return;
  }

  // 保存用例
  updateItemCaseById();
};


// 更新用例
const updateItemCaseById = async () => {
  const { data } = await UpdateItemCaseById({
    id: caseDetail.value.ID,
    testCaseName: caseDetail.value.testCaseName,
    beforeConditions: caseDetail.value.beforeConditions,
    operationSteps: caseDetail.value.operationSteps,
    expectedResult: caseDetail.value.expectedResult,
    realResult: caseDetail.value.realResult || ''
  })

  if (data.code == 200) {
    ElMessage.success(data.msg)
    caseEditVisible.value = false;
  } else {
    ElMessage.error(data.msg)
  }
}





// 删除模块方法
const deleteModule = async (module: any) => {
  // 判断是一级模块还是二级模块
  const isLevelTwo = module && (module.itemItemModule !== undefined && module.itemItemModule !== null);
  const moduleType = isLevelTwo ? '二级模块' : '一级模块';
  const moduleName = module.itemItemModuleName;
  
  try {
    await ElMessageBox.confirm(
      `确定要删除${moduleType}【${moduleName}】吗？\n删除后无法恢复，请谨慎操作！`,
      '删除确认',
      {
        confirmButtonText: '确定删除',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: false
      }
    );
    
    // 根据模块类型调用相应的删除接口
    let result;
    if (isLevelTwo) {
      result = await GetDeleteItemCaseModuleTwoById(module.ID);
    } else {
      result = await GetDeleteItemCaseModuleOneById(module.ID);
    }
    
    if (result.data.code === 200) {
      ElMessage.success(`${moduleType}删除成功`);
      // 刷新相关数据
      getItemOneModuleList();
      getItemTwoModuleList();
      getItemModuleCaseList();
      // 清除相关选择
      if (isLevelTwo) {
        selectedSubModules.value = selectedSubModules.value.filter(id => id !== module.ID);
      } else {
        selectedPrimaryModules.value = selectedPrimaryModules.value.filter(id => id !== module.ID);
        selectedSubModules.value = [];
      }
    } else {
      ElMessage.error(result.data.msg || `${moduleType}删除失败`);
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error(`${moduleType}删除失败：${error.message || '未知错误'}`);
    }
  }
};

// 废弃旧的通用弹窗显示方法

const handleModuleCommand = (command: string, module: any) => {
  if (command === 'edit') {
    // 根据是否存在父级ID来判断一级/二级模块（two模块通常包含 itemItemModule 作为父级ID）
    if (module && (module.itemItemModule !== undefined && module.itemItemModule !== null)) {
      openTowModuleDialogEditVisible(module);
    } else {
      openModuleDialogEditVisible(module);
    }
  } else if (command === 'delete') {
    // 调用删除模块方法
    deleteModule(module);
  } else if (command === 'link-cases') {
    openLinkCasesDialogVisible(module);
  }
};

// 选中的关联用例的ids
const selectedCases = ref<any[]>([]);
// 当前操作的模块
const openLinkCases = ref()
// 在脚本部分添加初始化
const allCasesToLink = ref<any[]>([]); // 初始化为空数组
// 查询的所有需求用例
const allRequirementToLink = ref();
// 根据需求名称查询
const searchRequirementQuery = ref();
// 关联模块用例模态框
const linkCasesDialogVisible = ref(false);
// 已经选择的用例列表
const linkedCases = ref<any>([]);
// 打开关联用例模态框
const openLinkCasesDialogVisible = (module: any) => {
  openLinkCases.value = module
  linkCasesDialogVisible.value = true;
  itemItemModuleId.value = module.ID;
  itemItemModuleName.value = module.itemItemModuleName
  getItemRequirementCaseList();//查询项目中所有需求用例
  getItemRequirementList();//查询项目中所有需求
  getLinkeModulList();//获取当前模块已经绑定用例
}
// 关闭关联用例模态框
const closeLinkCasesDialogVisible = () => {
  linkCasesDialogVisible.value = false;
  itemItemModuleName.value = '';
  itemItemModuleId.value = 0;
  searchRequirementQuery.value = 0;
}



// 根据选中需求搜索
const handleRequirementTolinkChange = () => {
  getItemRequirementCaseList();//查询项目中所有需求用例
}

// 关联用例
const confirmLinkCases = async () => {
  const caseIds = linkedCases.value.map((caseItem: any) => caseItem.ID);

  const { data } = await AddOneTwoModulItemRequirementList({
    "itemId": selectedProject.value,
    "itemItemModuleOneId": openLinkCases.value.itemItemModule,
    "itemItemModuleTwoId": openLinkCases.value.ID,
    "itemRequirementCaseIds": caseIds
  });

  if (data.code == 200) {
    ElMessage.success(data.msg);
    closeLinkCasesDialogVisible();
    // 刷新相关数据
    getItemModuleCaseList();
    getItemTwoModuleList();
  } else {
    ElMessage.error(data.msg);
  }
};
// 查询项目中所有需求用例
// 查询项目中所有需求用例
const getItemRequirementCaseList = async () => {
  try {
    const { data } = await GetItemRequirementCaseList({
      "itemId": selectedProject.value,
      "caseName": "",
      "itemRequirementId": searchRequirementQuery.value
    });

    if (data.code == 200) {
      allCasesToLink.value = (data.data || []) as any[]; // 确保总是返回数组
    } else {
      ElMessage.error(data.msg);
      allCasesToLink.value = [] as any[]; // 出错时重置为空数组
    }
  } catch (error) {
    console.error("获取用例列表失败:", error);
    allCasesToLink.value = [] as any[]; // 异常时重置为空数组
    ElMessage.error("获取用例列表失败，请稍后重试");
  }
}

// 查询项目中所有需求
const getItemRequirementList = async () => {
  const { data } = await GetItemRequirementList(selectedProject.value);
  if (data.code == 200) {
    allRequirementToLink.value = data.data;
  } else {
    ElMessage.error(data.msg)
  }
}


// 获取已经绑定的用例
const getLinkeModulList = async () => {
  try {
    const { data } = await GetLinkeModulList(openLinkCases.value.ID)
    if (data.code == 200) {
      linkedCases.value = data.data || []; // 确保总是返回数组
    } else {
      ElMessage.error(data.msg);
      linkedCases.value = []; // 出错时重置为空数组
    }
  } catch (error) {
    console.error("获取已关联用例失败:", error);
    linkedCases.value = [];
    ElMessage.error("获取已关联用例失败，请稍后重试");
  }
}

// 打开添加二级模块模态框
const openModuleDialogAddTwoVisible = (moduleId: number) => {
  // 根据ID找到对应的模块对象
  const module = oneModules.value.find((m: any) => m.ID === moduleId);
  if (module) {
    moduleDialogAddTwoVisible.value = true;
    itemItemModuleName.value = '';
    itemItemModuleId.value = module.ID;
  } else {
    ElMessage.error('未找到对应的模块信息');
  }
}
// 关闭添加二级模块模态框
const closeModuleDialogAddTwoVisible = () => {
  moduleDialogAddTwoVisible.value = false
}

// 提交添加二级模块模态框
const submitModuleDialogAddTwoVisible = async () => {

  if (!itemItemModuleName.value.trim()) {
    ElMessage.error('请输入模块名称');
    return;
  }

  if (!itemItemModuleId.value) {
    ElMessage.error('未找到父模块ID，请重新选择一级模块');
    return;
  }

  const { data } = await AddItemModuleTwo({
    "itemItemModuleId": itemItemModuleId.value,
    "itemItemModuleName": itemItemModuleName.value
  })

  if (data.code == 200) {
    ElMessage.success(data.msg)
    moduleDialogAddTwoVisible.value = false
    getItemOneModuleList();
    getItemTwoModuleList(); // 刷新二级模块数据以保持一致性
  } else {
    ElMessage.error(data.msg)
  }
}


const itemItemModuleId = ref(0);
// 打开编辑模态框
const openModuleDialogEditVisible = (module: any) => {
  moduleDialogEditVisible.value = true;
  itemItemModuleName.value = '';
  itemItemModuleId.value = module.ID;
  itemItemModuleName.value = module.itemItemModuleName;
}
const openTowModuleDialogEditVisible = (module: any) => {
  moduleDialogEditTwoVisible.value = true;
  itemItemModuleName.value = '';
  itemItemModuleId.value = module.ID;
  itemItemModuleName.value = module.itemItemModuleName;
}

// 关闭编辑模块模态框
const closeModuleDialogEditVisible = () => {
  moduleDialogEditVisible.value = false
  moduleDialogEditTwoVisible.value = false
}

// 提交编辑模块模态框
const submitModuleDialogEditVisible = async () => {

  if (!itemItemModuleName.value.trim()) {
    ElMessage.error('请输入模块名称');
    return;
  }

  const { data } = await UpdateItemModuleOne({
    "itemItemModuleId": itemItemModuleId.value,
    "itemItemModuleName": itemItemModuleName.value
  })

  if (data.code == 200) {
    ElMessage.success(data.msg)
    moduleDialogEditVisible.value = false
    getItemOneModuleList();
  } else {
    ElMessage.error(data.msg)
  }
}
// 提交编辑模块模态框
const submitModuleDialogEditTwoVisible = async () => {

  if (!itemItemModuleName.value.trim()) {
    ElMessage.error('请输入模块名称');
    return;
  }

  const { data } = await UpdateItemModuletwo({
    "itemItemModuleId": itemItemModuleId.value,
    "itemItemModuleName": itemItemModuleName.value
  })

  if (data.code == 200) {
    ElMessage.success(data.msg)
    moduleDialogEditTwoVisible.value = false
    getItemOneModuleList();
    getItemTwoModuleList();
  } else {
    ElMessage.error(data.msg)
  }
}


const itemItemModuleName = ref('')//模态框名称
// 打开添加模块模态框
const openModuleDialogAddVisible = () => {
  moduleDialogAddVisible.value = true;
  itemItemModuleName.value = '';
}
// 关闭添加模块模态框
const closeModuleDialogAddVisible = () => {
  moduleDialogAddVisible.value = false
}
// 提交添加模块模态框
const submitModuleDialogAddVisible = async () => {

  if (!itemItemModuleName.value.trim()) {
    ElMessage.error('请输入模块名称');
    return;
  }

  const { data } = await AddItemModuleOne({
    "itemItemId": selectedProject.value,
    "itemItemModuleName": itemItemModuleName.value
  })

  if (data.code == 200) {
    ElMessage.success(data.msg)
    moduleDialogAddVisible.value = false
    getItemOneModuleList();
  } else {
    ElMessage.error(data.msg)
  }
}

// 监听模块选择变化，更新子模块选择
watch(selectedPrimaryModules, (newVal) => {
  if (newVal.length === 0) {
    selectedSubModules.value = [];
  }
});

// 监听用例编辑表单中的模块变化，更新子模块选项
watch(() => caseEdit.form.module, (newVal) => {
  if (!newVal) {
    caseEdit.form.subModule = '';
  }
});


const getItemCaseListById = async () => {
  const { data } = await GetItemCaseListById({
    "projectid": selectedProject.value,
    "moduleIds": selectedPrimaryModules.value,
    "moduleTwoIds": selectedSubModules.value
  })
  if (data.code == 200) {

  } else {
    ElMessage.error(data.msg)
  }
}




// 获取所有项目测试用例数
const getAllItemCaseNumber = async (isAppend = false) => {
  if (isProjectLoading.value) return
  isProjectLoading.value = true
  
  // 计算本次请求的页面大小
  let currentPageSize = projectPagination.value.pageSize
  if (isAppend && projectPagination.value.page > 1) {
    // 第一次加载后，每次追加5条
    currentPageSize = projectStepPageSize
  }
  
  try {
    const params = {
      ...projectPagination.value,
      pageSize: currentPageSize
    }
    
    const { data } = await GetAllItemCaseNumber(params)
    if (data.code == 200) {
      const incoming = data.data
      
      // 确保数据字段正确映射
      if (incoming.list && Array.isArray(incoming.list)) {
        incoming.list.forEach((project: any) => {
          // 确保字段存在，如果不存在则设置为0
          project.demandCaseTotal = project.demandCaseTotal || 0
          project.projectCaseTotal = project.projectCaseTotal || 0
        })
      }
      
      if (projectPagination.value.page === 1) {
        projects.value = incoming
        console.log('首次加载项目:', incoming.list?.length || 0, '个')
      } else {
        // 追加数据以实现懒加载，过滤重复数据
        const existingIds = new Set(projects.value.list.map((project: any) => project.itemList.ID))
        const newProjects = (incoming.list || []).filter((project: any) => !existingIds.has(project.itemList.ID))
        
        console.log('追加加载项目:', {
          page: projectPagination.value.page,
          incoming: incoming.list?.length || 0,
          filtered: newProjects.length,
          existing: projects.value.list.length
        })
        
        projects.value.list = [...(projects.value.list || []), ...newProjects]
        projects.value.total = incoming.total
        projects.value.page = incoming.page
        projects.value.pageSize = incoming.pageSize
      }
      hasMoreProjects.value = (projects.value.list?.length || 0) < (projects.value.total || 0)
    } else {
      ElMessage.error(data.msg)
    }
  } finally {
    isProjectLoading.value = false
  }
}

// 左侧分页已移除

// 页面初始化调用接口
onMounted(() => {
  // 初始化数据
  allCasesToLink.value = [];
  linkedCases.value = [];
  
  // 重置分页状态
  projectPagination.value.page = 1
  hasMoreProjects.value = true
  projects.value.list = [] as any
  projects.value.total = 0
  
  getAllItemCaseNumber(false); // 首次加载，不使用追加模式
  getItemOneModuleList();//查询项目的一级模块，默认是3
  getItemModuleCaseList();//获取项目模块对应的用例
}
);



</script>
<style scoped>
/* 布局结构 */
.cases-view {
  height: 100%;
  background: #f7f8fa;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.cases-layout {
  display: flex;
  height: 100%;
  overflow: hidden;
}

.cases-sidebar {
  width: 340px;
  border-right: 2px solid #e2e8f0;
  background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
  display: flex;
  flex-direction: column;
  box-shadow: 6px 0 30px rgba(0, 0, 0, 0.08);
  position: relative;
  backdrop-filter: blur(20px);
}

/* 移除彩虹动画效果 */

/* 左侧搜索 */
.sidebar-header {
  padding: 8px;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-bottom: 2px solid #e2e8f0;
  position: relative;
  overflow: hidden;
}

/* 移除闪烁动画效果 */

.sidebar-search {
  position: relative;
  margin-top: 8px;
}

.search-input {
  width: 100%;
  height: 56px;
  padding: 16px 20px 16px 56px;
  border: 3px solid transparent;
  border-radius: 20px;
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  font-size: 15px;
  font-weight: 600;
  outline: none;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
}

.search-input:focus {
  background: #ffffff;
  border-color: #3b82f6;
  box-shadow: 0 0 0 6px rgba(59, 130, 246, 0.15), 0 12px 32px rgba(0, 0, 0, 0.15);
}

.search-input::placeholder {
  color: #94a3b8;
  font-weight: 600;
  opacity: 0.8;
}

.search-icon {
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
  color: #64748b;
  font-size: 20px;
  transition: color 0.3s ease;
  z-index: 2;
}

.search-input:focus + .search-icon {
  color: #3b82f6;
  filter: drop-shadow(0 2px 4px rgba(59, 130, 246, 0.3));
}

/* 左侧列表 */
.sidebar-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 20px;
}

.sidebar-item {
  position: relative;
  border: 2px solid transparent;
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  border-radius: 20px;
  cursor: pointer;
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
  margin-bottom: 24px;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
  backdrop-filter: blur(10px);
}

.sidebar-item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6, #06b6d4);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.sidebar-item:hover {
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
  border-color: #e2e8f0;
  background: linear-gradient(135deg, #ffffff 0%, #f1f5f9 100%);
}

.sidebar-item:hover::before {
  opacity: 1;
}

.sidebar-item.is-selected {
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15), 0 20px 40px rgba(59, 130, 246, 0.1);
  background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
  border-color: #3b82f6;
}

.sidebar-item.is-selected::before {
  opacity: 1;
  background: linear-gradient(90deg, #3b82f6, #1d4ed8);
}

.sidebar-item-content {
  padding: 28px;
  position: relative;
}

.sidebar-item-content::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 28px;
  right: 28px;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, #e2e8f0 50%, transparent 100%);
}

.sidebar-item-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 20px;
  position: relative;
}

.sidebar-item-title {
  font-size: 20px;
  font-weight: 800;
  color: #0f172a;
  line-height: 1.4;
  flex: 1;
  margin-right: 16px;
  background: linear-gradient(135deg, #0f172a 0%, #334155 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.sidebar-item-status {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  position: relative;
  overflow: hidden;
}

.sidebar-item-status::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  right: 2px;
  bottom: 2px;
  background: inherit;
  border-radius: 50%;
  filter: brightness(1.2);
}

.sidebar-item-meta {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 20px;
  padding: 20px;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-radius: 16px;
  border: 2px solid rgba(226, 232, 240, 0.6);
  position: relative;
  overflow: hidden;
}

.sidebar-item-meta::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6, #06b6d4);
}

.meta-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  min-width: 70px;
  position: relative;
}

.meta-item::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -10px;
  width: 1px;
  height: 30px;
  background: linear-gradient(180deg, transparent 0%, #e2e8f0 50%, transparent 100%);
  transform: translateY(-50%);
}

.meta-item:last-child::after {
  display: none;
}

.meta-icon {
  font-size: 18px;
  color: #475569;
  margin-bottom: 4px;
  transition: color 0.3s ease;
}

.sidebar-item:hover .meta-icon {
  color: #3b82f6;
}

.meta-label {
  font-size: 12px;
  color: #64748b;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  background: linear-gradient(135deg, #64748b 0%, #475569 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.meta-value {
  font-size: 18px;
  font-weight: 800;
  color: #0f172a;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.project-value {
  color: #047857;
  font-weight: 800;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.demand-value {
  color: #d97706;
  font-weight: 800;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.meta-divider {
  width: 2px;
  height: 50px;
  background: linear-gradient(180deg, transparent 0%, #cbd5e1 50%, transparent 100%);
  border-radius: 1px;
}



.sidebar-empty {
  text-align: center;
  padding: 56px 28px;
  color: #94a3b8;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-radius: 20px;
  margin: 28px 0;
  border: 3px dashed #cbd5e1;
  position: relative;
  overflow: hidden;
  backdrop-filter: blur(10px);
}

.sidebar-empty::before {
  content: "📋";
  display: block;
  font-size: 48px;
  margin-bottom: 20px;
  opacity: 0.8;
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.1));
}

.sidebar-empty::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, transparent 100%);
  pointer-events: none;
}

.sidebar-footer {
  padding: 24px 0 28px;
  text-align: center;
  color: #94a3b8;
  font-size: 14px;
  font-weight: 700;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-radius: 16px;
  margin: 0 16px;
  border: 2px solid #e2e8f0;
  position: relative;
  overflow: hidden;
  backdrop-filter: blur(10px);
}

/* 移除装饰线条 */

/* 主内容 */
.cases-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  position: relative;
  /* 创建新的层叠上下文 */
  isolation: isolate;
}

.main-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  border-bottom: 1px solid #e2e8f0;
  backdrop-filter: blur(20px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}

.main-header-inner {
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 20px;
}

.main-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
  margin-left: auto;
}

.tabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding: 4px;
  background: #f8fafc;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  margin-right: auto;
}

.tab {
  padding: 10px 20px;
  border: 2px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  color: #64748b;
  background: transparent;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  white-space: nowrap;
  min-width: 80px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.tab::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  transition: left 0.5s ease;
}

.tab:hover {
  background: #ffffff;
  color: #475569;
  border-color: #cbd5e1;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.tab:hover::before {
  left: 100%;
}

.tab.is-active {
  background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
  color: #ffffff;
  border-color: #3b82f6;
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
  font-weight: 600;
}

.tab.is-active::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 3px;
  background: linear-gradient(90deg, #fbbf24, #f59e0b);
  border-radius: 2px;
  animation: tabGlow 2s ease-in-out infinite alternate;
}

@keyframes tabGlow {
  0% {
    box-shadow: 0 0 5px rgba(251, 191, 36, 0.5);
  }
  100% {
    box-shadow: 0 0 15px rgba(251, 191, 36, 0.8);
  }
}

.main-content {
  flex: 1;
  overflow-y: auto;
  padding: 0 24px 0 24px;
  min-height: 0;
  position: relative;
  scroll-behavior: smooth;
  /* 优化滚动性能 */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

.section-gap {
  position: relative;
}

/* 项目用例视图容器 */
.project-cases-container {
  position: relative;
  z-index: 1;
}

/* 项目头信息 */
.project-header {
  display: flex;
  align-items: center;
  padding: 12px 24px;
  border-radius: 0;
  position: sticky;
  top: 0;
  z-index: 5;
  background: inherit;
  margin: -24px -24px 0 -24px;
  backdrop-filter: blur(10px);
  /* 防止穿梭显示 */
  transform: translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
}

.project-header-accent {
  width: 4px;
  height: 24px;
  border-radius: 2px;
  margin-right: 12px;
}

.project-header-title {
  font-weight: 600;
}

.project-header-sub {
  margin-left: 8px;
  font-size: 13px;
  color: #6b7280;
}

.table-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.op-gap {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.reviewed-btn {
  --el-button-bg-color: #e0f2fe;
  --el-button-border-color: #93c5fd;
  --el-button-text-color: #0ea5e9;
}

.btn-compact {
  padding-left: 12px !important;
  padding-right: 12px !important;
}

/* 卡片网格 */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 24px;
  overflow-y: auto;
  max-height: 700px;
}

@media (min-width: 768px) {
  .cards-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .cards-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* 需求用例卡片的响应式调整 */
@media (min-width: 768px) {
  .requirements-grid .card {
    min-height: 70px;
    padding: 12px;
  }
}

@media (min-width: 1024px) {
  .requirements-grid .card {
    min-height: 75px;
    padding: 14px;
  }
}

/* 需求用例卡片在不同屏幕尺寸下的优化 */
@media (max-width: 767px) {
  .requirements-grid .card {
    min-height: 65px;
    padding: 8px;
  }
  
  .requirements-grid .card-title {
    font-size: 12px;
    line-height: 1.2;
  }
  
  .requirements-grid .card-sub {
    font-size: 10px;
  }
}

.new-req-grid {
  max-height: 900px;
}

.tester-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 8px 0 16px 0;
}

.tester-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tester-tag {
  border-radius: 14px;
  padding: 8px 14px;
  border: 1px solid #e5e7eb;
  background: #fff;
  color: #374151;
  cursor: pointer;
  transition: all .16s ease;
}

.tester-tag:hover {
  border-color: #d1d5db;
  box-shadow: 0 2px 8px rgba(0,0,0,.06);
}

.tester-tag.is-active {
  background: #eef2ff;
  border-color: #c7d2fe;
  color: #4f46e5;
  font-weight: 600;
}

.card {
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 12px;
  background: #fff;
  cursor: pointer;
  transition: all 0.2s ease;
  min-height: auto;
  height: auto;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
  transform: translateY(-1px);
  border-color: #d1d5db;
}

.card.is-selected {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
  background: #f8faff;
  border-color: #3b82f6;
}

.requirements-grid .card.is-selected {
  background: linear-gradient(135deg, #f0f6ff 0%, #e0f2fe 100%);
}

.requirements-grid .card.is-selected::before {
  opacity: 1;
  height: 4px;
  background: linear-gradient(90deg, #3b82f6, #1d4ed8);
}

 .card-title-row {
   display: flex;
   align-items: flex-start;
   justify-content: space-between;
   margin-bottom: 6px;
   gap: 6px;
   min-height: auto;
 }
 
 .card-tags {
   display: flex;
   flex-direction: column;
   gap: 2px;
   align-items: flex-end;
   flex-shrink: 0;
   margin-top: -1px;
   margin-right: -2px;
   position: relative;
   z-index: 1;
   min-width: 60px;
   align-self: flex-start;
   position: absolute;
   top: 0;
   right: 0;
   flex-basis: 60px;
   margin-top: 2px !important;
   z-index: 10 !important;
   background: rgba(255, 255, 255, 0.9);
   border-radius: 4px;
   padding: 2px;
   backdrop-filter: blur(4px);
   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
   border: 1px solid rgba(255, 255, 255, 0.2);
   transition: all 0.2s ease;
 }

.requirements-grid .card-tags:hover {
  background: rgba(255, 255, 255, 1);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
  transform: translateY(-1px);
}

/* 需求用例卡片最终优化完成 */
.requirements-grid .card {
  transition: box-shadow 0.3s ease !important;
}

.requirements-grid .card:hover {
  box-shadow: 0 6px 20px rgba(59, 130, 246, 0.15) !important;
}

.requirements-grid .card.is-selected {
  box-shadow: 0 4px 16px rgba(59, 130, 246, 0.2) !important;
}
 
 .tester-tag {
   font-size: 10px;
   padding: 1px 4px;
   max-width: 100px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
   line-height: 1.2;
 }

.card-title {
  font-weight: 600;
}

.card-sub {
  font-size: 12px;
  color: #6b7280;
  margin-top: 4px;
  line-height: 1.3;
}

.audit-sub {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.audit-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1;
  border: 1px solid #e5e7eb;
  background: #fff;
}

.audit-badge--passed {
  color: #16a34a;
  border-color: #bbf7d0;
  background: #f0fdf4;
}

.audit-badge--pending {
  color: #b45309;
  border-color: #fde68a;
  background: #fffbeb;
}

.count-highlight {
  color: #3b82f6;
  font-weight: 600;
}

/* 需求用例卡片特殊样式 */
.requirements-grid .card {
  padding: 10px;
  min-height: 60px;
  max-height: none;
  overflow: visible;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  box-sizing: border-box;
  height: auto;
  width: 100%;
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
}

.requirements-grid .card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  border-radius: 12px 12px 0 0;
  opacity: 0.6;
  transition: all 0.2s ease;
}

.requirements-grid .card-title {
  font-size: 13px;
  line-height: 1.3;
  max-height: none;
  overflow: visible;
  word-break: break-word;
  hyphens: auto;
  flex: 1;
  min-height: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-right: 4px;
  max-width: calc(100% - 80px);
  padding-right: 4px;
  align-self: flex-start;
  text-align: left;
  padding-right: 70px;
  flex-basis: calc(100% - 80px);
  margin-right: 8px !important;
}

.requirements-grid .card-sub {
  font-size: 11px;
  margin-top: 3px;
  margin-bottom: 2px;
  flex-shrink: 0;
  line-height: 1.2;
  text-align: left;
  color: #6b7280;
  margin-top: 6px;
  clear: both;
  width: 100%;
  padding-top: 4px !important;
}

.requirements-grid .card-title-row {
  margin-bottom: 4px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  min-height: auto;
  flex-shrink: 0;
  width: 100%;
  align-items: stretch;
  position: relative;
  min-height: 20px;
  flex-wrap: wrap;
  margin-bottom: 8px !important;
}

.requirements-grid .card:hover::before {
  opacity: 1;
  height: 3px;
}

.requirements-grid .card:hover {
  background: linear-gradient(135deg, #ffffff 0%, #f0f4ff 100%);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
}

/* 需求用例卡片内容优化 */
.requirements-grid .card-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.requirements-grid .card-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 0;
}

.requirements-grid .card-footer {
  margin-top: auto;
  flex-shrink: 0;
}

/* 需求用例卡片动画效果 */
/* 移除重复的transition定义 */

.requirements-grid .card::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, #e5e7eb, transparent);
  opacity: 0.5;
}

/* 需求用例卡片内容布局优化 */
.requirements-grid .card > * {
  position: relative;
  z-index: 1;
}

.requirements-grid .card-title-row {
  z-index: 2;
}

.requirements-grid .card-sub {
  z-index: 1;
}

/* 需求用例卡片最终优化 */
.requirements-grid .card {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.requirements-grid .card:hover {
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);
}

.requirements-grid .card.is-selected {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5), 0 2px 8px rgba(59, 130, 246, 0.1);
}

/* 需求用例卡片内容完全展示优化 */
.requirements-grid .card {
  overflow: visible !important;
  max-height: none !important;
  height: auto !important;
  min-height: auto !important;
  display: block !important;
  flex-direction: column !important;
  padding-bottom: 12px !important;
}

.requirements-grid .card-title {
  overflow: visible !important;
  max-height: none !important;
  white-space: normal !important;
  word-wrap: break-word !important;
  hyphens: auto !important;
  line-height: 1.4 !important;
  margin-bottom: 4px !important;
  padding-bottom: 2px !important;
}

/* el-table/对话框等保留必要覆盖（纯CSS） */
:deep(.el-table) {
  font-size: 14px;
}

/* 确保模态框固定定位，不跟随滚动 */
:deep(.el-dialog) {
  position: fixed !important;
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%) !important;
  margin: 0 !important;
}

:deep(.el-dialog__wrapper) {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
}

:deep(.el-overlay) {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
}

:deep(.el-table th) {
  background-color: #f8fafc;
  color: #606266;
  font-weight: 600;
}

:deep(.el-dialog) {
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
}

/* 输入框外观 */
:deep(.el-input__wrapper) {
  border-radius: 8px;
}

/* 滚动条样式 */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 300px;
  border: 1px dashed #eee;
  border-radius: 8px;
  margin-top: 10px;
  background-color: #fafafa;
}

/* 表格样式调整 */
:deep(.el-table) {
  --el-table-border-color: transparent;
  --el-table-border: none;
}

:deep(.el-table__inner-wrapper) {
  height: 100%;
  display: flex;
  flex-direction: column;
}

:deep(.el-table__body) {
  flex: 1;
}

:deep(.el-table__empty-block) {
  width: 100% !important;
}

/* 单元格样式调整 */
:deep(.el-table td.el-table__cell),
:deep(.el-table th.el-table__cell) {
  border-right: none;
}

:deep(.el-table td.el-table__cell:last-child),
:deep(.el-table th.el-table__cell:last-child) {
  padding-right: 12px;
}

:deep(.el-table .cell) {
  padding-left: 12px;
  padding-right: 12px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

/* 表格容器样式 */
.table-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 模块选择器样式 */
.module-selector {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin: 0 -24px 0 -24px;
  padding: 20px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 0;
  border-left: none;
  border-right: none;
  border-top: none;
  position: sticky;
  top: 40px;
  z-index: 5;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
  transition: box-shadow 0.3s ease;
  /* 防止穿梭显示 */
  transform: translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
}

.module-selector:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* 确保表格在模块选择器下方正确显示 */
.el-table {
  position: relative;
  z-index: 1;
  margin-top: 16px;
}

/* 为模块选择器添加顶部渐变遮罩 */
.module-selector::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6, #06b6d4);
  opacity: 0.6;
  border-radius: 0;
}

.module-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.module-title {
  font-size: 14px;
  color: #4b5563;
  font-weight: 600;
  margin-bottom: 4px;
}

.module-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-start;
}

.module-tag {
  padding: 6px 12px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  background-color: #f3f4f6;
  color: #4b5563;
  font-size: 13px;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: fit-content;
  max-width: 200px;
}

.module-tag:hover {
  background-color: #e5e7eb;
  border-color: #d1d5db;
  color: #374151;
}

.module-tag.is-selected {
  background-color: #3b82f6;
  border-color: #3b82f6;
  color: #fff;
}

.module-tag-content {
  cursor: pointer;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.module-actions-btn {
  padding: 2px;
  color: inherit;
  opacity: 0.7;
}

.module-actions-btn:hover {
  opacity: 1;
  background-color: rgba(255, 255, 255, 0.1);
}

.module-count {
  font-size: 11px;
  opacity: 0.8;
  margin-left: 4px;
}

.module-empty {
  color: #9ca3af;
  font-style: italic;
  padding: 8px 12px;
}

.add-module-btn {
  margin-left: 0;
  height: 32px;
  padding: 0 12px;
  font-size: 12px;
  align-self: flex-start;
}

 .add-module-btn .el-icon {
   margin-right: 4px;
 }
 
 .dialog-footer {
   display: flex;
   justify-content: flex-end;
   gap: 12px;
 }
 
 /* 懒加载状态提示样式 */
 .list-footer {
   text-align: center;
   padding: 16px;
   color: #9ca3af;
   font-size: 14px;
   background: #f9fafb;
   border-top: 1px solid #e5e7eb;
   margin-top: 8px;
   border-radius: 0 0 8px 8px;
 }
 
 /* 对话框懒加载状态提示定位 */
 .dialog-lazy-footer {
   position: fixed;
   bottom: 80px;
   left: 50%;
   transform: translateX(-50%);
   z-index: 2001;
   min-width: 200px;
   border-radius: 8px;
   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
 }
 
 .dialog-lazy-footer.is-loading {
   bottom: 100px;
 }

/* 关联用例对话框样式 */
.link-cases-container {
  padding: 0 8px 8px 8px;
}

.link-cases-header {
  margin: -8px -8px 12px -8px;
  padding: 12px 16px;
  border-bottom: 1px solid #e5e7eb;
  background: #fafafa;
}

.link-cases-header h4 {
  margin: 0;
  color: #111827;
  font-size: 18px;
  font-weight: 600;
}

.link-cases-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  height: 500px;
  min-height: 400px;
}

.left-panel,
.right-panel {
  display: flex;
  flex-direction: column;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
  min-height: 320px;
}

.panel-header {
  padding: 12px 16px;
  background: #f9fafb;
  border-bottom: 1px solid #e5e7eb;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.panel-header-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

.inline-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.form-label {
  font-size: 12px;
  color: #6b7280;
}

.panel-header h5 {
  margin: 0;
  font-size: 14px;
  color: #1f2937;
  font-weight: 600;
}

.search-controls {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: nowrap;
  min-width: 0;
}

/* 调整该页面内对话框的内外边距与字体布局 */
:deep(.el-dialog__header) {
  padding: 12px 16px 8px;
}

:deep(.el-dialog__body) {
  padding: 8px 12px 12px;
}

.panel-actions {
  padding: 10px 12px;
  border-top: 1px solid #e5e7eb;
  background: #f9fafb;
  text-align: center;
}

@media (max-width: 1200px) {
  .link-cases-content {
    grid-template-columns: 1fr;
    height: 72vh;
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .module-selector {
    padding: 16px;
    gap: 16px;
    position: sticky;
    top: 50px;
    margin: 0 -16px 20px -16px;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
  
  .project-header {
    margin: -16px -16px 0 -16px;
    padding: 12px 16px;
    top: 0;
    border-radius: 0;
  }

  
  .module-tags {
    gap: 6px;
  }
  
  .module-tag {
    padding: 4px 8px;
    font-size: 12px;
    max-width: 150px;
  }
}

@media (max-width: 1024px) {
  .module-selector {
    top: 35px;
  }
  
  .project-header {
    top: 0;
  }
}

/* 确保在较小屏幕上模块选择器仍然可见 */
@media (max-height: 600px) {
  .module-selector {
    position: relative;
    top: auto;
    margin: 0 0 20px 0;
    border-radius: 8px;
    border: 1px solid #e5e7eb;
    border-left: 1px solid #e5e7eb;
    border-right: 1px solid #e5e7eb;
  }
  
  .project-header {
    position: relative;
    top: auto;
    margin: 0 0 16px 0;
    border-radius: 8px;
  }
}

/* 最终优化：防止穿梭显示和闪烁 */
.module-selector,
.project-header {
  /* 硬件加速 */
  transform: translateZ(0);
  /* 优化渲染性能 */
  will-change: transform;
  /* 防止背面可见 */
  backface-visibility: hidden;
  /* 确保元素在正确的层叠上下文中 */
  contain: layout style paint;
}

/* 优化滚动容器 */
.main-content {
  /* 防止滚动时的闪烁 */
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
  /* 优化滚动性能 */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* 防止滚动时的重绘 */
  contain: layout style paint;
}

/* 响应式标签按钮优化 */
@media (max-width: 768px) {
  .tabs {
    gap: 6px;
    padding: 3px;
    border-radius: 10px;
  }
  
  .tab {
    padding: 8px 16px;
    font-size: 13px;
    min-width: 70px;
    border-radius: 8px;
  }
  
  .main-header-inner {
    padding: 12px 16px;
    gap: 16px;
  }
}

@media (max-width: 480px) {
  .tabs {
    gap: 4px;
    padding: 2px;
  }
  
  .tab {
    padding: 6px 12px;
    font-size: 12px;
    min-width: 60px;
    border-radius: 6px;
  }
  
  .main-header-inner {
    padding: 10px 12px;
    gap: 12px;
  }
}

/* 统一风格覆盖：简化配色与阴影，贴合全局白卡 + 灰边框风格 */
.cases-sidebar {
  background: #fff;
  border-right: 1px solid #e5e7eb;
  box-shadow: none;
}

.sidebar-header {
  background: #fff;
  border-bottom: 1px solid #e5e7eb;
}

.search-input {
  height: 40px;
  padding: 8px 12px 8px 40px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: #fff;
  font-weight: 400;
  box-shadow: none;
}

.search-input:focus {
  border-color: #409EFF;
  box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.12);
}

.sidebar-item {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  box-shadow: none;
}

.sidebar-item::before {
  display: none;
}

.sidebar-item:hover {
  background: #fff;
  border-color: #dcdfe6;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
}

.sidebar-item.is-selected {
  background: #f5faff;
  border-color: #409EFF;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.16);
}

.main-header {
  background: #fff;
  border-bottom: 1px solid #e5e7eb;
  box-shadow: none;
}

.tabs {
  background: transparent;
  border: none;
  padding: 0;
  gap: 12px;
}

.tab {
  padding: 8px 12px;
  border: none;
  box-shadow: none;
  color: #606266;
  background: transparent;
}

.tab::before {
  display: none;
}

.tab:hover {
  background: #f5f7fa;
  color: #303133;
  border: none;
  transform: none;
  box-shadow: none;
}

.tab.is-active {
  color: #409EFF;
  background: transparent;
  border: none;
  position: relative;
}

.tab.is-active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -8px;
  height: 2px;
  background: #409EFF;
  border-radius: 1px;
  box-shadow: none;
  animation: none;
}

.cards-grid {
  overflow: visible;
  max-height: none;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 16px;
}

.card {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: #fff;
  box-shadow: none;
}

.card:hover {
  border-color: #dcdfe6;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
  transform: none;
}

.card.is-selected {
  border-color: #409EFF;
  background: #f5faff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.16);
}

.requirements-grid .card {
  background: #fff;
  padding: 12px;
}

.requirements-grid .card::before {
  display: none;
}

.requirements-grid .card:hover {
  background: #fff;
}

.requirements-grid .card-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-weight: 600;
}

.count-highlight {
  color: #409EFF;
}

.module-selector {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-top: none;
  box-shadow: none;
}

.module-tag {
  background: #f5f7fa;
  border: 1px solid #e5e7eb;
}

.module-tag.is-selected {
  background: #409EFF;
  border-color: #409EFF;
}

.project-header {
  background: #fff;
}

/* 左侧项目列表进一步与右侧卡片统一 */
.sidebar-list {
  padding: 12px;
}

.sidebar-item {
  margin-bottom: 12px;
  border-radius: 8px;
}

.sidebar-item.is-selected::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 0;
  bottom: 0;
  width: 3px;
  background: #409EFF;
  border-radius: 2px;
}

.sidebar-item-content {
  padding: 14px;
}

.sidebar-item-content::after {
  display: none;
}

.sidebar-item-header {
  margin-bottom: 8px;
  align-items: center;
}

.sidebar-item-title {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
  background: none !important;
  -webkit-text-fill-color: initial !important;
  -webkit-background-clip: initial !important;
  background-clip: initial !important;
}

.sidebar-item-meta {
  background: transparent;
  border: none;
  padding: 6px 0 0;
  gap: 12px;
}

.meta-item {
  flex-direction: row;
  align-items: center;
  gap: 6px;
  min-width: auto;
}

.meta-item::after,
.meta-divider {
  display: none;
}

.meta-label {
  font-size: 12px;
  color: #909399;
  letter-spacing: 0;
  font-weight: 400;
  -webkit-text-fill-color: initial !important;
  background: none !important;
}

.meta-value {
  font-size: 13px;
  color: #303133;
  text-shadow: none;
  font-weight: 600;
}

.project-value { color: #16a34a; }
.demand-value { color: #d97706; }

/* 去掉左侧项目卡片标题右侧的小圆点 */
.sidebar-item-status { display: none !important; }

/* 需求卡片头部内联布局与标签样式简化 */
.requirements-grid .card-title-row {
  align-items: center;
  gap: 10px;
}

.requirements-grid .card-tags {
  position: static !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  margin: 0 !important;
}

.requirements-grid .tester-tag {
  background: #f5f7fa;
  color: #606266;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 12px;
}

.neutral-tag {
  background: #f5f7fa !important;
  color: #606266 !important;
  border: 1px solid #e5e7eb !important;
  border-radius: 999px !important;
}

/* 更宽或更窄屏幕下的列数自适应 */
@media (min-width: 1440px) {
  .cards-grid {
    grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  }
}

@media (max-width: 1024px) {
  .cards-grid {
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  }
}

</style>
